Add unicsv.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Thu, 12 Jan 2006 20:35:43 +0000 (20:35 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Thu, 12 Jan 2006 20:35:43 +0000 (20:35 +0000)
gpsbabel/unicsv.c [new file with mode: 0644]

diff --git a/gpsbabel/unicsv.c b/gpsbabel/unicsv.c
new file mode 100644 (file)
index 0000000..d0a4b7d
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+    Universal CSV - support for csv files, divining field order from the header.
+
+    Copyright (C) 2006 Robert Lipe,  robertlipe@usa.net
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+#include "defs.h"
+#include "csv_util.h"
+
+#define MYNAME "unicsv"
+
+static FILE *fin;
+
+/* This structure must contain only ints.  Firstval must be first.
+ * This is block initialized.
+ */
+struct {
+       int firstval;
+       int latcol;
+       int loncol;
+       int namecol;
+       int desccol;
+       int notescol;
+       int altcol;
+       int urlcol;
+} unicsv_fieldpos;
+
+static float unicsv_altscale;
+static char *unicsv_fieldsep;
+
+static
+arglist_t unicsv_args[] = {
+       {0, 0, 0, 0, 0}
+};
+
+/* helpers */
+
+/* fread_buff: returns only left and right trimmed non-empty lines or NULL */
+static char *
+fread_buff(char *buff, const size_t buff_size, FILE *fin)
+{
+       char *result;
+       
+       while ((result = fgets(buff, buff_size, fin)))
+       {
+               result = lrtrim(result);
+               if (*result != '\0') break;
+       }
+       return result;
+}
+
+#define UNICSV_IS(f) (0 == strcmp(s, f))
+#define UNICSV_CONTAINS(f) (0 != strstr(s, f))
+
+static void
+unicsv_fondle_header(char *ibuf)
+{
+       char *s;
+       int i;
+       int *ip = &unicsv_fieldpos.firstval;
+
+       for (i = 0; i < sizeof(unicsv_fieldpos) / sizeof(int); i++, ip++) {
+               *ip = -1;
+       }
+
+       /* Convert the entire header to lower case for convenience. 
+        * If we see a tab in that header, we decree it to be tabsep.
+        */
+       unicsv_fieldsep = ",";  
+       for (s = ibuf; *s; s++) {
+               if (*s == '\t') {
+                       unicsv_fieldsep = "\t";
+               }
+               else if (*s == ';') {
+                       unicsv_fieldsep = ";";
+               }
+               else {
+                       *s = tolower(*s);
+               }
+       }
+
+       s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0);
+       for (i=0; s; i++,s = csv_lineparse(NULL, unicsv_fieldsep, "", 0)) {
+               if (UNICSV_CONTAINS("lat")) {
+                       unicsv_fieldpos.latcol = i;
+               }
+               else if (UNICSV_IS("lon") || UNICSV_CONTAINS("long")) {
+                       unicsv_fieldpos.loncol = i;
+               }
+               else if (UNICSV_CONTAINS("desc")) {
+                       unicsv_fieldpos.desccol = i;
+               }
+               else if (UNICSV_IS("name")) {
+                       unicsv_fieldpos.namecol = i;
+               }
+               else if (UNICSV_CONTAINS("notes")) {
+                       unicsv_fieldpos.notescol = i;
+               }
+               else if (UNICSV_CONTAINS("alt")) {
+                       unicsv_fieldpos.altcol = i;
+                       if (UNICSV_CONTAINS("ft") || UNICSV_CONTAINS("feet")) {
+                               unicsv_altscale = 0.3048;
+                       }
+               }
+               else if (UNICSV_IS("url")) {
+                       unicsv_fieldpos.urlcol = i;
+               }
+/* todo: speed, course, hdop, sat, date, time, maybe a few others */
+       }
+}
+
+static void
+unicsv_rd_init(const char *fname)
+{
+       char ibuf[1024];
+       unicsv_altscale = 1.0;
+
+       fin = xfopen(fname, "r", MYNAME);
+
+       if (NULL != fread_buff(ibuf, sizeof(ibuf), fin))
+               unicsv_fondle_header(ibuf);
+       else
+               unicsv_fieldsep = NULL;
+}
+
+static void
+unicsv_rd_deinit(void)
+{
+       fclose(fin);
+       fin = NULL;
+}
+
+static void
+unicsv_parse_one_line(char *ibuf)
+{
+       char *s;
+       waypoint *wpt;
+       int i;
+
+       s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0);
+       if (s == NULL) return;
+       
+       wpt = waypt_new();
+
+       for (i=0; s; i++, s = csv_lineparse(NULL, unicsv_fieldsep, "", 0)) {
+               if (i == unicsv_fieldpos.latcol) {
+                       human_to_dec( s, &wpt->latitude, &wpt->longitude, 1 );
+               }
+               else if (i == unicsv_fieldpos.loncol) {
+                       human_to_dec( s, &wpt->latitude, &wpt->longitude, 2 );
+               }
+               else if (i == unicsv_fieldpos.namecol) {
+                       wpt->shortname = xstrdup(s);
+               }
+               else if (i == unicsv_fieldpos.desccol) {
+                       wpt->description = xstrdup(s);
+               }
+               else if (i == unicsv_fieldpos.notescol) {
+                       wpt->notes = xstrdup(s);
+               }
+               else if (i == unicsv_fieldpos.urlcol) {
+                       wpt->url = xstrdup(s);
+               }
+               else if (i == unicsv_fieldpos.altcol) {
+                       wpt->altitude = atof(s) * unicsv_altscale;
+               }
+       }
+       waypt_add(wpt);
+}
+
+static void 
+unicsv_rd()
+{
+       char buff[1024];
+
+       if (unicsv_fieldsep == NULL) return;
+       
+       while (fread_buff(buff, sizeof(buff), fin)) {
+               unicsv_parse_one_line(buff);
+       }
+}
+
+/* --------------------------------------------------------------------------- */
+
+ff_vecs_t unicsv_vecs = {
+       ff_type_file,
+       { ff_cap_read, 0, 0},
+       unicsv_rd_init,
+       NULL,
+       unicsv_rd_deinit, 
+       NULL,
+       unicsv_rd,
+       NULL,
+       NULL,
+       unicsv_args,
+       CET_CHARSET_ASCII, 0    /* can be changed with -c ... */
+};